package im.youni.horus.core.recoder;

import im.youni.horus.core.SecondTag;
import im.youni.horus.core.common.BaseUtils;
import im.youni.horus.core.common.buffer.IntBuf;
import im.youni.horus.core.MetricsStorge;
import im.youni.horus.core.common.NameThreadFactory;
import im.youni.horus.core.common.buffer.IntBufPool;

import java.util.Map;
import java.util.concurrent.*;

/**
 * Recorder定时器
 * @author sims
 * 需要定时器，则初始化
 */
public class SyncRecord {

    private final long monitorInterval;

    static final IntBufPool intBufPool = IntBufPool.getInstance();

    // 定时任务执行器
    private final ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(3, new NameThreadFactory("DubboMonitorSendTimer", true));

    // 统计信息收集定时器
    private final ScheduledFuture<?> sendFuture;

    /**
     * 初始化metrics同步器
     * @param ttl
     */
    public SyncRecord(int ttl) {
        this.monitorInterval = ttl;
        // 启动统计信息收集定时器
        sendFuture = scheduledExecutorService.scheduleWithFixedDelay(new Runnable() {
            public void run() {
                try {
                    // 收集统计信息
                    collect();
                } catch (Throwable t) {
                    t.printStackTrace();
                }
            }
        }, monitorInterval, monitorInterval, TimeUnit.MILLISECONDS);
    }

    /**
     * 收集原始数据，入Metrics数据集
     */
    private void collect() {
        RecordFactory recordFactory = RecordFactory.getInstance();
        ConcurrentMap<SecondTag, Recorder> recorder = recordFactory.changeReference();
        ConcurrentHashMap<SecondTag, String> storge = null;
        if (recorder != null && recorder.size() > 0) {
            // 采集到数据，再进行storge的切换
            storge = MetricsStorge.get().getReference(true);
            for (Map.Entry<SecondTag, Recorder> entry : recorder.entrySet()) {
                IntBuf intBuf = intBufPool.acquire(entry.getValue().getDiffCount() << 1);
                entry.getValue().fillStroge(intBuf);
                // 获取metrics存储，并标记需要清理
                storge.put(entry.getKey(), BaseUtils.intBufStrFormat(intBuf.toString()));
                entry.getKey().errorCount = entry.getValue().getErrorCount();
            }
            // 清理recorder数据
            recorder.clear();
        }
    }
}
